// 经纬度转空间坐标和极坐标
function lngLat2ThetaPhiXYZ(lngLat, radius) {
    const theta = 90 - lngLat[1];
    const phi = 180 - lngLat[0];
    const sinTheta = Math.sin(theta / 180 * Math.PI);
    const cosTheta = Math.cos(theta / 180 * Math.PI);
    const sinPhi = Math.sin(phi / 180 * Math.PI);
    const cosPhi = Math.cos(phi / 180 * Math.PI);
    let x = cosPhi * sinTheta;
    let y = cosTheta;
    let z = sinPhi * sinTheta;
    if (radius) {
        x *= radius;
        y *= radius;
        z *= radius;
    }

    return {
        theta: theta,
        phi: phi,
        x: x,
        y: y,
        z: z
    };
}

/**
* 将笛卡尔空间直角坐标系中的坐标转换为经纬度，以角度表示
* @param vertice
* @return {Array}
*/
function XYZ2lngLat(x, y, z, radius) {
    var sin2 = y / radius;
    var radianLat = asinSafely(sin2);
    var cos2 = Math.cos(radianLat);
    var sin1 = x / (radius * cos2);
    if (sin1 > 1) {
        sin1 = 1;
    }
    if (sin1 < -1) {
        sin1 = -1;
    }
    var cos1 = z / (radius * cos2);
    if (cos1 > 1) {
        cos1 = 1;
    }
    if (cos1 < -1) {
        cos1 = -1;
    }
    var radianLog = asinSafely(sin1);
    if (sin1 >= 0) {
        //经度在[0,π]
        if (cos1 >= 0) {
            //经度在[0, π/2]之间
            radianLog = radianLog;
        } else {
            //经度在[π/2, π]之间
            radianLog = Math.PI - radianLog;
        }
    } else {
        //经度在[-π, 0]之间
        if (cos1 >= 0) {
            //经度在[-π/2, 0]之间
            radianLog = radianLog;
        } else {
            //经度在[-π,-π/2]之间
            radianLog = -radianLog - Math.PI;
        }
    }
    var degreeLat = radianToDegree(radianLat);
    var degreeLog = radianToDegree(radianLog);
    return [degreeLog, degreeLat];
}

const ONE_RADIAN_EQUAL_DEGREE = 57.29577951308232;//=>180/Math.PI
const ONE_DEGREE_EQUAL_RADIAN = 0.017453292519943295;//=>Math.PI/180

/**
 * 角度转弧度
 * @param degree
 * @return {*}
 */
function degreeToRadian(degree) {
    return degree * ONE_DEGREE_EQUAL_RADIAN;
}

/**
 * 弧度转角度
 * @param radian
 * @return {*}
 */
function radianToDegree(radian) {
    return radian * ONE_RADIAN_EQUAL_DEGREE;
}

function asinSafely(value) {
    if (value > 1) {
        value = 1;
    }
    if (value < -1) {
        value = -1;
    }
    return Math.asin(value);
}

module.exports = {
    lngLat2ThetaPhiXYZ: lngLat2ThetaPhiXYZ,
    XYZ2lngLat: XYZ2lngLat
}